package utils

import (
	"bytes"
	"crypto/md5"
	"fmt"
	"github.com/astaxie/beego/cache"
	"math/rand"
	"reflect"
	"runtime"
	"strconv"
	"strings"
	"time"
	"unicode"
)

//截取字符串，包括中文
func Show_substr(s string, l int) string {
	if len(s) <= l {
		return s
	}
	ss, sl, rl, rs := "", 0, 0, []rune(s)
	for _, r := range rs {
		rint := int(r)
		if rint < 128 {
			rl = 1
		} else {
			rl = 2
		}

		if sl+rl > l {
			break
		}
		sl += rl
		ss += string(r)
	}
	return ss
}

//获取字符串长度，包括中文
func Show_strlen(s string) int {
	sl := 0
	rs := []rune(s)
	for _, r := range rs {
		rint := int(r)
		if rint < 128 {
			sl++
		} else {
			sl += 2
		}
	}
	return sl
}

//md5加密
func Md5(str string) string {
	strNew := md5.Sum([]byte(str))
	return fmt.Sprintf("%x", strNew)
}


//是否在数组中
func Is_InStrArray(val string, array []string) bool {
	for _, v := range array {
		if v == val {
			return true
		}
	}
	return false
}

//转为日期
func Data(timestamp int) string {
	timestamp1 := int64(timestamp)

	//转化所需模板
	timeLayout := "2006-01-02 15:04:05"

	//进行格式化
	datetime := time.Unix(timestamp1, 0).Format(timeLayout)
	return datetime
}

//获取一个随机数
func GetRandInt() int{
	s2 := rand.NewSource(time.Now().Unix())
	r2 := rand.New(s2)
	return r2.Int()
}

//获取指定位数的随机数
func GetRandInt1(max int) int{
	s2 := rand.NewSource(time.Now().Unix())
	r2 := rand.New(s2)
	return r2.Intn(max)
}

//获取数组中随机一个
func GetRand(arr []interface{}) interface{}{
	if len(arr) <= 0 {
		return nil
	}

	index := GetRandInt1(len(arr))
	return getRandCore(arr, index)
}

func getRandCore(arr []interface{}, index int) interface{}{
	if index == 1 {
		return arr[0]
	}

	result := getRandCore(arr[1:], index - 1)

	return result
}

//view内置函数 乘法
func Ride(num1, num2 interface{}) (result int){
	result = cache.GetInt(num1) * cache.GetInt(num2)
	return
}

//view内置函数 加法
func Add(num1, num2 interface{}) (result int){
	result = cache.GetInt(num1) + cache.GetInt(num2)
	return
}

//view内置函数 时间转换
func Dates(time interface{}) (result string){
	result = Data(cache.GetInt(time))
	return
}

//获取结构体字段
func GetStructField(st reflect.Type) (fields []string){
	//获取结构体字段
	for i:= 0; i< st.NumField(); i++{
		fields = append(fields, st.Field(i).Name)
	}
	return
}

//转为int
func GetInt(v interface{}) int {
	switch result := v.(type) {
	case int:
		return result
	case int32:
		return int(result)
	case int64:
		return int(result)
	default:
		if d := GetString(v); d != "" {
			value, _ := strconv.Atoi(d)
			return value
		}
	}
	return 0
}

//转为string
func GetString(v interface{}) string {
	switch result := v.(type) {
	case string:
		return result
	case []string:
		return strings.Join(result, "")
	case []byte:
		return string(result)
	default:
		if v != nil {
			return fmt.Sprint(result)
		}
	}
	return ""
}

//驼峰转换为小写
func Camel2Case(name string) string {
	var buf bytes.Buffer
	for i, r := range name {
		if unicode.IsUpper(r) {
			if i != 0 {
				buf.WriteString("_")
			}
			buf.WriteRune(unicode.ToLower(r))
		} else {
			buf.WriteRune(r)
		}
	}
	return buf.String()
}

//获取小值
func Min(a, b int) int{
	if a > b {
		return b
	}
	return a
}

//获取大值
func Max(a, b int) int{
	if a > b {
		return a
	}
	return b
}

//获取协程id
func GetGID() uint64 {
	b := make([]byte, 64)
	b = b[:runtime.Stack(b, false)]
	b = bytes.TrimPrefix(b, []byte("goroutine "))
	b = b[:bytes.IndexByte(b, ' ')]
	n, _ := strconv.ParseUint(string(b), 10, 64)
	return n
}